package com.yang.controller;

import com.yang.exception.BusinessException;
import com.yang.pojo.SysField;
import com.yang.pojo.SysFile;
import com.yang.service.SysFieldService;
import com.yang.service.SysFileService;
import com.yang.utils.JsonResult;
import com.yang.utils.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

@RestController
@RequestMapping("/file")
public class TransformController {

    /**
     * 文件路径
     * 本地测试时注释线上地址，使用本地地址
     * 打包时注释本地地址，使用线上地址
     */
//    @Value("${SystemConfigure.onLinePath}") //线上地址
    @Value("${SystemConfigure.localPath}")  //本地地址
    private String filePath;

    @Resource
    private SysFileService sysFileService;
    @Resource
    private SysFieldService sysFieldService;

    @GetMapping("/getPath")
    public Map<String, Object> getPath() {
        JsonResult jsonResult = new JsonResult();
        String data = System.getProperty("user.dir");
        jsonResult.setData(data);
        jsonResult.setMsg("获取成功");
        jsonResult.setCode("200");
        return jsonResult.getValues();
    }

    /**
     * 解析Excel表头
     * @param excelName
     * @return
     */
    @GetMapping("/readHeader")
    public Map<String, Object> readHeader(@RequestParam("excelName") String excelName) {
        JsonResult jsonResult = new JsonResult();
        SysFile sysFile = sysFileService.findByOriginalNewFileName(excelName);
        Integer id = sysFile.getId();//文件主键
        Sheet sheet = outWeb(excelName).getSheetAt(0);
        int firstRowIndex = sheet.getFirstRowNum();//首行 表头
        Row row = sheet.getRow(firstRowIndex);
        int firstCellIndex = row.getFirstCellNum();//首列
        int lastCellIndex = row.getLastCellNum();//尾列
        for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {   //遍历列
            Cell cell = row.getCell(cIndex);
            if (StringUtils.isNotEmpty(String.valueOf(cell))){
                String cName = cell.toString().replaceAll("\n", "").replaceAll(" ", "");
                SysField sysField = new SysField();
                sysField.setSysFileId(id);
                sysField.setCIndex(cIndex);
                sysField.setCName(cName);
                sysField.setCreateTime(new Date());
                sysFieldService.inset(sysField);
            }
        }
        jsonResult.setMsg("获取成功");
        jsonResult.setCode("200");
        return jsonResult.getValues();
    }

    /**
     * 获取表头内容
     * @param fileId
     * @return
     */
    @GetMapping("/getHeader")
    public Map<String,Object> getHeader(@RequestParam("fileId") String fileId){
        JsonResult jsonResult = new JsonResult();
        List<SysField> byFileId = sysFieldService.findByFileId(Integer.valueOf(fileId));
        jsonResult.setMsg("获取成功");
        jsonResult.setCode("200");
        jsonResult.setData(byFileId);
        return jsonResult.getValues();
    }

    /**
     * 解析Excel内容
     * @param excelName
     * @return
     */
    @GetMapping("/readAndWrit")
    public Map<String, Object> readAndWrit(@RequestParam("excelName") String excelName) {
        JsonResult jsonResult = new JsonResult();

        List<String> content = new ArrayList<>();
        String str = "单选题\r\n";//单选题
        String str1 = "多选题\r\n";//多选题
        String str2 = "判断题\r\n";//判断题

        //读取Excel
        Sheet sheet = outWeb(excelName).getSheetAt(0);     //读取sheet 0

        int firstRowIndex = sheet.getFirstRowNum() + 1;   //第一行是列名，所以不读
        int lastRowIndex = sheet.getLastRowNum();
        for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {   //遍历行
            Row row = sheet.getRow(rIndex);
            if (StringUtils.isNotEmpty(row.toString())) {
                int firstCellIndex = row.getFirstCellNum();
                int lastCellIndex = row.getLastCellNum();
                for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {   //遍历列
                    Cell cell = row.getCell(cIndex);
                    if (StringUtils.isNotEmpty(String.valueOf(cell)) && String.valueOf(row.getCell(5)).equals("单选题")) {
                        String string = getString(cIndex, cell, rIndex);
                        if (StringUtils.isNotEmpty(string)) {
                            str += string;
                        }
                    }

                    if (StringUtils.isNotEmpty(String.valueOf(cell)) && String.valueOf(row.getCell(5)).equals("多选题")) {
                        String string = getString(cIndex, cell, rIndex);
                        if (StringUtils.isNotEmpty(string)) {
                            str1 += string;
                        }
                    }

                    if (StringUtils.isNotEmpty(String.valueOf(cell)) && String.valueOf(row.getCell(5)).equals("判断题")) {
                        String string = getString(cIndex, cell, rIndex);
                        if (StringUtils.isNotEmpty(string)) {
                            str2 += string;
                        }
                    }

                }
            }
        }

        content.add(str);
        content.add(str1);
        content.add(str2);

        /*
         * 准备写入word
         */
        XWPFDocument document = new XWPFDocument();
        OutputStream stream = null;
        BufferedOutputStream bufferStream = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists()) {
                dir.mkdirs();
            }

            String fileName = UUID.randomUUID().toString().replace("-", "") + ".docx";
            File file = new File(filePath + fileName);
            file.createNewFile();

            stream = new FileOutputStream(file);
            bufferStream = new BufferedOutputStream(stream, 1024);
            XWPFParagraph p1 = document.createParagraph();// 创建一个段落
            p1.setAlignment(ParagraphAlignment.CENTER);// 设置居中
            XWPFRun r1 = p1.createRun();
            r1.setBold(true);// 加粗
            r1.setTextPosition(30);// 行距
            r1.setText("题  库");// 文档标题
            r1.setFontSize(18);// 字号
            r1.addCarriageReturn();// 换行
            XWPFParagraph p2 = document.createParagraph();
            XWPFRun r2 = p2.createRun();
            for (int i = 0; i < content.size(); i++) {
                r2.setText(content.get(i));
                r2.addCarriageReturn();
            }
            r2.setFontFamily("仿宋");// 字体
            r2.setFontSize(14);// 字号
            document.write(stream);
            stream.close();
            bufferStream.close();

            SysFile sysFile = sysFileService.findByOriginalNewFileName(excelName);
            sysFile.setTargetFileName(fileName);
            sysFile.setTargetFilePath(filePath + fileName);
            sysFile.setModifyTime(new Date());
            sysFileService.update(sysFile);

            jsonResult.setData(fileName);
            jsonResult.setCode("200");
            jsonResult.setMsg("转换成功");

        } catch (Exception ex) {
            throw new BusinessException("转换失败");
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new BusinessException("转换失败");
                }
            }

            if (bufferStream != null) {
                try {
                    bufferStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new BusinessException("转换失败");
                }
            }
        }

        return jsonResult.getValues();
    }


    @PostMapping(value = "/upload")
    public Map<String, Object> upload(@RequestParam("file") MultipartFile file) throws IOException {
        JsonResult jsonResult = new JsonResult();
        //不能上传空文件
        if (file.isEmpty()) {
            throw new BusinessException("文件不能为空");
        }
        String originalFilename = file.getOriginalFilename();//原文件名
        assert originalFilename != null;
        String subfix = originalFilename.substring(originalFilename.indexOf(".") + 1);
        String fileName = UUID.randomUUID().toString().replace("-", "") + "." + subfix;//新文件名

        //上传到Linux 服务器
        String finalFilePath = filePath + fileName;
        try {
            File uploadFile = new File(finalFilePath);
            file.transferTo(uploadFile);

            /*
             * 将原文件名，新文件路径（路径 + 新文件名）存储到数据库
             */
            SysFile sysFile = new SysFile();
            sysFile.setOriginalFileName(originalFilename);//原文件名
            sysFile.setOriginalNewFileName(fileName);//文件上传成功之后的新名称
            sysFile.setOriginalFilePath(finalFilePath);//文件上传之后的真实完整路径
            sysFile.setCreateTime(new Date());
            sysFile.setModifyTime(new Date());
            sysFileService.insert(sysFile);
            SysFile byOriginalNewFileName = sysFileService.findByOriginalNewFileName(fileName);
            Integer id = byOriginalNewFileName.getId();

            jsonResult.setMsg("上传成功");
            jsonResult.setCode("200");
            jsonResult.setData(fileName);
        } catch (IOException e) {
            throw e;
        }

        return jsonResult.getValues();
    }

    @GetMapping("/downLoad")
    public Map<String, Object> downLoad(@RequestParam("fileName") String fileName, HttpServletResponse response, HttpServletRequest request) {
        JsonResult jsonResult = new JsonResult();
        boolean res = downLoadFile(fileName, response, request);
        if (res) {
            jsonResult.setCode("200");
            jsonResult.setMsg("下载成功");
        } else {
            jsonResult.setCode("400");
            jsonResult.setMsg("下载失败，请联系管理员");
        }
        return jsonResult.getValues();
    }

    /**
     * 获取文本方法
     */
    private String getString(Integer cIndex, Cell cell, Integer rIndex) {
        String str = "";
        if (cIndex == 2) {//难度
            str += "难度： " + cell.toString() + "\r\n";
        }
        if (cIndex == 6) {//试题正文
            str += rIndex + "、" + cell.toString() + "\r\n";
        }
        if (cIndex == 7) {//选项A
            str += "A：" + cell.toString() + "\r\n";
        }
        if (cIndex == 8) {//选项B
            str += "B：" + cell.toString() + "\r\n";
        }
        if (cIndex == 9) {//选项C
            str += "C：" + cell.toString() + "\r\n";
        }
        if (cIndex == 10) {//选项D
            str += "D：" + cell.toString() + "\r\n";
        }
        if (cIndex == 11) {//选项C
            str += "E：" + cell.toString() + "\r\n";
        }
        if (cIndex == 12) {//选项D
            str += "F：" + cell.toString() + "\r\n";
        }
        if (cIndex == 13) {//答案
            str += "答案： " + cell.toString() + "\r\n";
        }
        if (cIndex == 16) {//试题来源
            str += "试题来源： " + cell.toString() + "\r\n" +
                    "\r\n";
        }
        return str;
    }

    /**
     * 下载方法
     *
     * @param fileName
     * @param response
     * @param request
     * @return
     */
    private boolean downLoadFile(String fileName, HttpServletResponse response, HttpServletRequest request) {
        String absolutePath = filePath + fileName;
        File f = new File(absolutePath);
        if (!f.exists()) {
            throw new BusinessException("文件不存在！");
        }

        response.setContentType("application/force-download;charset=UTF-8");
        final String userAgent = request.getHeader("USER-AGENT");
        try {
            if (StringUtils.contains(userAgent, "MSIE") || StringUtils.contains(userAgent, "Edge")) {// IE浏览器
                fileName = URLEncoder.encode(fileName, "UTF8");
            } else if (StringUtils.contains(userAgent, "Mozilla")) {// google,火狐浏览器
                fileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器
            }
            response.setHeader("Content-disposition", "attachment; filename=" + fileName);
        } catch (UnsupportedEncodingException e) {
            throw new BusinessException("下载失败");
        }
        InputStream in = null;
        OutputStream out = null;
        try {

            //获取要下载的文件输入流
            in = new FileInputStream(absolutePath);
            int len = 0;
            //创建数据缓冲区
            byte[] buffer = new byte[1024];
            //通过response对象获取outputStream流
            out = response.getOutputStream();
            //将FileInputStream流写入到buffer缓冲区
            while ((len = in.read(buffer)) > 0) {
                //使用OutputStream将缓冲区的数据输出到浏览器
                out.write(buffer, 0, len);
            }
        } catch (Exception e) {
            throw new BusinessException("下载失败");
        } finally {
            try {
                if (out != null)
                    out.close();
                if (in != null)
                    in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * Excel输出流
     */
    public Workbook outWeb(String excelName) {
        try {
            File excel = new File(filePath + excelName);
            if (!excel.isFile() || !excel.exists()) {   //判断文件是否存在
                throw new BusinessException("系统找不到指定文件");
            }

            String[] split = excel.getName().split("\\.");  //.是特殊字符，需要转义！！！！！
            Workbook wb;
            if ("xls".equals(split[1])) {
                FileInputStream fis = new FileInputStream(excel);   //文件流对象
                wb = new HSSFWorkbook(fis);
                return wb;
            } else if ("xlsx".equals(split[1])) {
                wb = new XSSFWorkbook(excel);
                return wb;
            } else {
                throw new BusinessException("文件类型错误!");
            }
        } catch (Exception e) {
            throw new BusinessException("转换错误");
        }
    }

}
